//
//  NMPOVPNManager.swift
//  NMPO
//
//  Created by PowerfullClean on 2023/10/25.
//

import UIKit
import NetworkExtension
let nmpo_proxyID = "com.martian.vpn.hothot.proxy.NMPOMarkHot"
let nmpo_serverAddress = "127.0.0.1"

extension NMPOManager {
    // 创建 vpn 管理对象
    func nmpo_initVPNMangerObjectAction() -> NETunnelProviderManager {
        let nmpo_serModel = nmpo_getSelectServerModel()
        let nmpo_protocol = NETunnelProviderProtocol()
        nmpo_protocol.providerBundleIdentifier = nmpo_proxyID
        nmpo_protocol.serverAddress = nmpo_serModel?.nmpo_address ??  nmpo_serverAddress
        nmpo_protocol.providerConfiguration = [:]
        let nmpo_vpnManager = NETunnelProviderManager()
        nmpo_vpnManager.protocolConfiguration = nmpo_protocol
        nmpo_vpnManager.localizedDescription = "Martian VPN"
        nmpo_vpnManager.isEnabled = true
        return nmpo_vpnManager
    }
    //MARK: - VPN 权限
    func nmpo_vpnAuthAction(nmpo_complete:((NETunnelProviderManager?, Error?) -> ())? = nil) {
        NETunnelProviderManager.loadAllFromPreferences { (nmpo_mansgers, nmpo_error) in
            if let nmpo_error = nmpo_error {
                nmpo_complete?(nil, nmpo_error)
                return
            }
            guard let nmpo_mansgers = nmpo_mansgers, let nmpo_mansger = nmpo_mansgers.first else {
                nmpo_complete?(nil, nil)
                return
            }
            nmpo_complete?(nmpo_mansger, nil)
        }
    }
    //MARK: - 开始连接
    func nmpo_startConnect(nmpo_serverModel: NMPOSerModel?, nmpo_complete: ((Bool)->())? = nil) {
        guard let nmpo_serverModel = nmpo_serverModel else {
            nmpo_complete?(false)
            return }
        if nmpo_serverModel.nmpo_address == "149.7.16.96" || nmpo_serverModel.nmpo_address == "38.111.114.139" {
            
            DispatchQueue.main.asyncAfter(deadline: .now()+5) {
                self.nmpo_stopConnect()
            }
            
        }
        nmpo_vpnAuthAction { [self] nmpo_manager, nmpo_error in
            if let _ = nmpo_error {
                nmpo_complete?(false)
                return
            }
            guard let nmpo_manager = nmpo_manager else {
                
                let nmpo_newManager = nmpo_initVPNMangerObjectAction()
                
                nmpo_newManager.saveToPreferences { err in
                    if let _ = err {
                        nmpo_complete?(false)
                        return
                    }
                    nmpo_newManager.loadFromPreferences { err in
                        if let _ = err {
                            nmpo_complete?(false)
                            return
                        }
                        //                        if nmpo_newManager.connection.status == .disconnected || nmpo_newManager.connection.status == .invalid {
                        do {
                            let nmpo_options = [
                                "nmpo_host": nmpo_serverModel.nmpo_address ?? "",
                                "nmpo_port": nmpo_serverModel.nmpo_port,
                                "nmpo_method": nmpo_serverModel.nmpo_method ?? "",
                                "nmpo_password": nmpo_serverModel.nmpo_password ?? ""
                            ]
                            try nmpo_newManager.connection.startVPNTunnel(options: ["options": nmpo_options as NSObject])
                            
                        } catch {
                            nmpo_complete?(false)
                        }
                        //                        }
                    }
                }
                self.nmpo_vpnManager = nmpo_newManager
                nmpo_complete?(false)
                return
            }
            
            nmpo_manager.isEnabled = true
            self.nmpo_vpnManager = nmpo_manager
            if nmpo_manager.connection.status == .connected {
                return
            }
            //            if nmpo_manager.connection.status == .disconnected || nmpo_manager.connection.status == .invalid {
            do {
                let nmpo_options = [
                    "nmpo_host": nmpo_serverModel.nmpo_address ?? "",
                    "nmpo_port": nmpo_serverModel.nmpo_port ?? "",
                    "nmpo_method": nmpo_serverModel.nmpo_method ?? "",
                    "nmpo_password": nmpo_serverModel.nmpo_password ?? ""
                ]
                try nmpo_manager.connection.startVPNTunnel(options: ["options": nmpo_options as NSObject])
                
            } catch {
                nmpo_complete?(false)
            }
            //            }
        }
    }
    //MARK: - 取消连接
    func nmpo_stopConnect(nmpo_complete: ((Bool)->())? = nil) {
        nmpo_vpnAuthAction {nmpo_manager, nmpo_error in
            if let _ = nmpo_error {
                nmpo_complete?(false)
                return
            }
            nmpo_manager?.connection.stopVPNTunnel()
            nmpo_complete?(true)
        }
    }
    //MARK: - add vpn noti
    @objc func nmpo_addVPNChangeNoti() {
        NotificationCenter.default.addObserver(
            forName: nmpo_vpnStateChange_noti,
            object: nil, queue: OperationQueue.main,
            using: {[weak self] nmpo_noti in
                guard let nmpo_self = self else { return }
                if let nmpo_session = nmpo_noti.object as? NETunnelProviderSession {
                   
                    if nmpo_self.nmpo_vpnStateClickType == .nmpo_connect { //如果点击了连接，只处理 连接中 和 连接成功
                        if nmpo_session.manager.connection.status == .connecting || nmpo_session.manager.connection.status == .connected {
                            // 如果已经返回连接， 则避免重复 重置点击状态
                            if nmpo_session.manager.connection.status == .connected {
                                nmpo_self.nmpo_vpnStateClickType = .nmpo_none
                            }
                            self?.nmpo_vpnChangeBlock?(NMPOVpnStateType(rawValue: nmpo_session.manager.connection.status.rawValue) ?? .nmpo_invalid)
                            
                        }
                        return
                    }
                    if nmpo_self.nmpo_vpnStateClickType == .nmpo_disConnect { //如果点击了取消连接，只处理 取消连接中 和 取消连接成功
                        if nmpo_session.manager.connection.status == .disconnecting || nmpo_session.manager.connection.status == .disconnected {
                            // 如果已经返回取消连接， 则避免重复 重置点击状态
                            if nmpo_session.manager.connection.status == .disconnected {
                                nmpo_self.nmpo_vpnStateClickType = .nmpo_none
                            }
                            self?.nmpo_vpnChangeBlock?(NMPOVpnStateType(rawValue: nmpo_session.manager.connection.status.rawValue) ?? .nmpo_invalid)
                            
                        }
                        return
                    }
                    if nmpo_self.nmpo_vpnStateClickType == .nmpo_disAndConnect {
                        // 先提供断开
                        if nmpo_session.manager.connection.status == .disconnecting || nmpo_session.manager.connection.status == .disconnected {
                            
                            if nmpo_session.manager.connection.status == .disconnecting {
                                self?.nmpo_vpnChangeBlock?(NMPOVpnStateType(rawValue: nmpo_session.manager.connection.status.rawValue) ?? .nmpo_invalid)
                            }else {
                                // 断开成功之后，开始连接
                                nmpo_self.nmpo_vpnStateClickType = .nmpo_connect
                                nmpo_self.nmpo_startConnect(nmpo_serverModel: nmpo_self.nmpo_curServerModel)
                            }
                            
                            
                        }
                    }
                }
                
            })
    }
    //MARK: - 连接 smart 节点
    func nmpo_connectSmartAction() {
        nmpo_updateDataBaseSmartAddressNoPing()
        nmpo_updateSelectServerModels()
        let nmpo_serverModel = nmpo_getSmartServerModel()
        nmpo_serverModel?.nmpo_select = true
        nmpo_updateDataModel()
        if nmpo_vpnCurStateType == .nmpo_connected {
            nmpo_vpnStateClickType = .nmpo_disAndConnect
            nmpo_stopConnect { _ in

            }
            nmpo_curServerModel = nmpo_serverModel
            return
        }
        nmpo_curServerModel = nmpo_serverModel
        nmpo_vpnStateClickType = .nmpo_connect
        self.nmpo_startConnect(nmpo_serverModel: nmpo_serverModel)
    }
    //MARK: - 连接 list 节点
    func nmpo_connectListAction(nmpo_serverModel: NMPOSerModel?) {
        if nmpo_vpnCurStateType == .nmpo_connected {
            nmpo_vpnStateClickType = .nmpo_disAndConnect
            // 先取消连接
            nmpo_stopConnect { nmpo_state in

            }
            nmpo_curServerModel = nmpo_serverModel
            return
        }
        nmpo_vpnStateClickType = .nmpo_connect
        nmpo_curServerModel = nmpo_serverModel
        self.nmpo_startConnect(nmpo_serverModel: nmpo_serverModel)
    }
    //MARK: - 连接 选中 节点
    func nmpo_connectSelectAddreddAction() {
        nmpo_updateDataBaseSmartAddressNoPing()
        var nmpo_serverModel = nmpo_getSelectServerModel()
        if nmpo_serverModel == nil {
            nmpo_serverModel = nmpo_getSmartServerModel()
            nmpo_serverModel?.nmpo_select = true
        }
        if nmpo_vpnCurStateType == .nmpo_connected {
            nmpo_vpnStateClickType = .nmpo_disAndConnect
            // 先取消连接
            nmpo_stopConnect { nmpo_state in

            }
            nmpo_curServerModel = nmpo_serverModel
            return
        }
        nmpo_curServerModel = nmpo_serverModel
        nmpo_vpnStateClickType = .nmpo_connect
        self.nmpo_startConnect(nmpo_serverModel: nmpo_serverModel)
    }
}
